#include <stdio.h>
#include <string.h>

/* 
整形提升
在表达式计算时，各种整型首先要提升为int类型，如果int类型不足以表示则要提升为unsigned int类型；然后执行表达式的运算。

整形提升规则
有符号的：整型提升时是按照变量的补码被截断时的最高位是什么进行补位的，如果截断后最高位（即最左面）的一位数为 1 则在最高位前补 1 ，如果最高位是 0 则在前面补 0 ，补够32位即int类型即可。
无符号的：直接在被截断的前面补 0 即可。

为什么会有整形提升？
整型提升的意义在于：表达式的整型运算要在CPU的相应运算器件内执行，CPU内整型运算器(ALU)的操作数的字节长度一般就是int的字节长度，同时也是CPU的通用寄存器的长度。
因此，即使两个char类型的相加，在CPU执行时实际上也要先转换为CPU内整型操作数的标准长度。
通用CPU是难以直接实现两个8比特字节直接相加运算（虽然机器指令中可能有这种字节相加指令）。
所以，表达式中各种长度可能小于int长度的整型值，都必须先转换为int或unsigned int，然后才能送入CPU去执行运算。

*/ 

/*
int main()
{   
    char a = -1; // -1 占4个字节 ，char类型的a只能保存一个字节。 默认是有符号的。
    // 原码：10000000 00000000 00000000 00000000
    // 反码：11111111 11111111 11111111 11111110
    // 补码：11111111 11111111 11111111 11111111

    // a存八个bit位，即 11111111
    signed char b = -1;
    // b存八个bit位，即 11111111
    unsigned char c = -1;
    // c存八个bit位，即 11111111

    // a打印整数， 整形提升 char提升为整形，按原符号位(1)提升，a的补码变为 11111111 11111111 11111111 11111111
    // b是带符号的，与a相同。
    // c打印整数 无符号位，整形提升前面补0，c的补码变为 00000000 00000000 00000000 11111111
    printf("a=%d,b=%d,c=%d \n",a,b,c); // a=-1,b=-1,c=255
    return 0;
}
*/


int main()
{
    char a = 3;
    char b = 127;
    char c = a + b;
    printf("%d \n",c); // 输出 -126
    /*
        1、
        3的补码
        00000000 00000000 00000000 00000011
        123的补码
        00000000 00000000 00000000 01111111
        2、
        进行表达式运算时，a b会发生截断，阶段后的值
        a : 00000011 
        b : 01111111
        3、
        相加时，会发生整形提升。因为默认是有符号的，按照截断后最高位进行补位
        a提升为：00000000 00000000 00000000 00000011
        b提升为：00000000 00000000 00000000 01111111
        相加后 ：00000000 00000000 00000000 10000010(补码)
        4、
        因为c为char类型，只能存放8个比特位，所以也需要截断，变为 10000010
        5、
        以d%进行printf时,c需要进行整形提升。c是有符号的，按照阶段后最高位进行补位
        c的补码：11111111 11111111 11111111 10000010
        c的反码：11111111 11111111 11111111 10000001
        c的原码：10000000 00000000 00000000 01111110（因为是负数。符号位不动，其他位取反）
        c转为十进制：-126
    */

    char w = -128;
    printf("ww=== %u \n",w); // 输出  ww=== 4294967168
    /*
        %u 打印十进制的无符号数字；%d 打印十进制的有符号数字。
        1、
        a的原码：00000000 00000000 00000000 10000000
        a的反码：11111111 11111111 11111111 01111111
        a的补码：11111111 11111111 11111111 10000000
        2、
        保存到a时，发生截断：100000000
        3、进行打印时，发生整形提升。
        a的补码：11111111 11111111 11111111 10000000
        %u打印，即认为a是无符号的值，所以a的原码与补码相同
        a的原码：11111111 11111111 11111111 10000000
        转为10进制后，为4294967168
    */
    return 0;
}
